package com.xpf.controller;

import com.xpf.pojo.Users;
import com.xpf.pojo.bo.ShopcartBO;
import com.xpf.pojo.bo.UserBO;
import com.xpf.pojo.vo.UserVO;
import com.xpf.service.UserService;
import com.xpf.utils.*;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.catalina.User;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

@Api(value = "注册登录", tags = {"用于注册登录的相关接口"})
@RestController //所有请求都是json对象
@RequestMapping("passport")
public class PassportController extends BaseController{

    @Autowired
    private UserService userService;

    @Autowired
    private RedisOperator redisOperator;

    @ApiOperation(value = "用户是否存在", notes = "用户是否存在1",httpMethod = "GET")
    @GetMapping("/usernameIsExist")
    public JSONResult usernameIsExist(@RequestParam String username){
        // 1.判断用户是否不能为空
        if (StringUtils.isBlank(username)){
            return JSONResult.errorMsg("用户名不能为空");
        }

        //2. 查找注册的用户是否存在
        boolean isExist = userService.usernameIsExist(username);
        if (isExist)
            return JSONResult.errorMsg("用户名已存在");

        //3. 请求成功，用户名没有重复
        return JSONResult.ok();
    }

    @ApiOperation(value = "用户注册", notes = "用户注册2",httpMethod = "POST")
    @PostMapping("/regist")
    public JSONResult Register(@RequestBody UserBO userBO, HttpServletRequest request,
                               HttpServletResponse response){
        String username = userBO.getUsername();
        String password = userBO.getPassword();
        String confirmPassword = userBO.getConfirmPassword();

        //1.用户名和密码不能为空
        if (StringUtils.isBlank(username) ||
            StringUtils.isBlank(password) ||
            StringUtils.isBlank(confirmPassword))
            return JSONResult.errorMsg("用户名或密码不能为空");
        //2.查询用户是否存在
        boolean isExist = userService.usernameIsExist(username);
        if (isExist)
            return JSONResult.errorMsg("用户名已存在");
        //3.密码长度不能少于6位数
        if (password.length() < 6){
            return JSONResult.errorMsg("密码长度不能少于6位数");
        }
        //4.判断两次输入密码是否一致
        if (!password.equals(confirmPassword)){
            return JSONResult.errorMsg("密码输入不一致");
        }
        //5.注册用户
        Users userResult = userService.createUser(userBO);

        //6. 注册完前端会跳转到首页， 让cookie记录用户注册信息，直接登录
//        userResult = setNullProperty(userResult);

        //生成用户token，存入redis会话(实现用户redis会话)
        UserVO userVO = conventUserVO(userResult);

        CookieUtils.setCookie(request, response, "user", JsonUtils.objectToJson(userVO),true);

        // 同步购物车数据
        synchShopcartData(userResult.getId(),request,response);
        return JSONResult.ok();
    }



    /**
     * 注册登录成功后，同步cookie和redis中的购物车数据
     */
    private void synchShopcartData(String userId,HttpServletRequest request,HttpServletResponse response){
        /**
         * 1. redis中无数据，如果cookie中的购物车为空，那么这个时候不做任何处理
         *                 如果cookie中的购物车不为空，此时直接放入redis中
         * 2. redis中有数据，如果cookie中的购物车为空，那么直接把redis购物车覆盖本地cookie
         *                 如果cookie中的购物车不空，如果cookie中的某个商品在redis中存在，
         *                     则以cookie为主，删除redis中的，
         *                     把cookie中的商品直接覆盖redis中（参考京东）
         * 3. 同步到redis中去了以后，覆盖本地cookie购物车的数据，保证本地购物车的数据是同步最新的
         */
        //从redis中获取购物车
        String shopcartJsonRedis = redisOperator.get(FOODIE_SHOPCART + ":" + userId);

        //从cookie中获取购物车
        String shopcartStrCookie = CookieUtils.getCookieValue(request, FOODIE_SHOPCART, true);

        if (StringUtils.isBlank(shopcartJsonRedis)){
            // redis为空，cookie不为空，直接把cookie中的数据放入到redis中
            if (StringUtils.isNotBlank(shopcartStrCookie)){
                redisOperator.set(FOODIE_SHOPCART + ":" +userId, shopcartStrCookie);
            }
        }else {
            //redis为空，cookie不为空，合并cookie和redis中购物车的商品数据（同一商品则覆盖redis中的）
            if (StringUtils.isNotBlank(shopcartStrCookie)){
                /**
                 * 1. 已经存在的，把cookie中对应的数量，覆盖redis (参考京东)
                 * 2. 该项商品标记为待删除,统一放入一个待删除的list
                 * 3. 从cookie中清理所有的待删除list
                 * 4. 合并redis和cookie中的数据
                 * 5. 更新到redis和cookie中
                 */
                List<ShopcartBO> shopcartListRedis = JsonUtils.jsonToList(shopcartJsonRedis,ShopcartBO.class);
                List<ShopcartBO> shopcartListCookie = JsonUtils.jsonToList(shopcartStrCookie,ShopcartBO.class);

                //等待删除的list
                List<ShopcartBO> pendingDeletList = new ArrayList<>();

                for (ShopcartBO redisShopcart : shopcartListRedis) {
                    String redisSpecId = redisShopcart.getSpecId();

                    for (ShopcartBO cookieShopcart : shopcartListCookie) {
                        String cookieSpecId = cookieShopcart.getSpecId();
                        if (redisSpecId.equals(cookieSpecId)){
                            // 使用cookie中的购买数量覆盖redis中的
                            redisShopcart.setBuyCounts(cookieShopcart.getBuyCounts());
                            // 把cookieShopcart放入到待删除列表，用于最后的删除
                            pendingDeletList.add(cookieShopcart);
                        }
                    }
                }

                //从cookie中清理所有的待删除list
                shopcartListCookie.removeAll(pendingDeletList);
                //合并redis和cookie中的数据
                shopcartListRedis.addAll(shopcartListCookie);
                //更新到redis和cookie中
                redisOperator.set(FOODIE_SHOPCART + ":" +userId, JsonUtils.objectToJson(shopcartListRedis));
                CookieUtils.setCookie(request, response, FOODIE_SHOPCART, JsonUtils.objectToJson(shopcartListRedis),true);
            }else{
                //redis不为空，cookie为空，直接把redis覆盖cookie
                CookieUtils.setCookie(request, response, FOODIE_SHOPCART, shopcartJsonRedis,true);
            }
        }

    }

    @ApiOperation(value = "用户登录", notes = "用户登录",httpMethod = "POST")
    @PostMapping("/login")
    public JSONResult UserLogin(@RequestBody UserBO userBO, HttpServletRequest request,
                                HttpServletResponse response) throws Exception{
        String username = userBO.getUsername();
        String password = userBO.getPassword();

        //1.用户名和密码不能为空
        if (StringUtils.isBlank(username) ||
                StringUtils.isBlank(password) )
            return JSONResult.errorMsg("用户名或密码不能为空");

        //2.用户登录
        Users userResult = userService.queryUserForLogin(username, MD5Utils.getMD5Str(password));
        if (userResult == null)
            return JSONResult.errorMsg("用户名或密码错误");

//        userResult = setNullProperty(userResult);

        //生成用户token，存入redis会话(实现用户redis会话)
        UserVO userVO = conventUserVO(userResult);

        CookieUtils.setCookie(request, response, "user", JsonUtils.objectToJson(userVO),true);

        // 同步购物车数据
        synchShopcartData(userResult.getId(),request,response);
        return JSONResult.ok(userResult);
    }

    private Users setNullProperty(Users resultUsers){
        resultUsers.setPassword(null);
        resultUsers.setCreatedTime(null);
        resultUsers.setEmail(null);
        resultUsers.setMobile(null);
        resultUsers.setUpdatedTime(null);
        return resultUsers;
    }

    @ApiOperation(value = "用户退出登录", notes = "用户退出登录",httpMethod = "POST")
    @PostMapping("/logout")
    public JSONResult logout(@RequestParam String userId, HttpServletRequest request, HttpServletResponse response){
        //清空用户相关消息的cookie
        CookieUtils.deleteCookie(request, response, "user");

        //用户退出登录，需要清空购物车
        CookieUtils.deleteCookie(request, response,FOODIE_SHOPCART);
        //分布式会话中需要清除用户数据
        redisOperator.del(REDIS_USER_TOKEN + ":" + userId);
        return JSONResult.ok();
    }

}
